/*
  Copyright © 2010  Vinícius dos Santos Oliveira

      This file is part of Touché.

      Touché is free software: you can redistribute it and/or modify
      it under the terms of the GNU Lesser General Public License as published
      by the Free Software Foundation, either version 3 of the License, or
      (at your option) any later version.

      This program is distributed in the hope that it will be useful,
      but WITHOUT ANY WARRANTY; without even the implied warranty of
      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      GNU Lesser General Public License for more details.

      You should have received a copy of the GNU Lesser General Public License
      along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */

#include "scene.h"
#include "widgets/pushbuttonitem.h"
#include "widgets/slideritem.h"
#include <QFileDialog>
#include <QDir>
using namespace Touche;
#include <QGraphicsSvgItem>

#define TOUCHE_SHOULD_SKIP_THIS

#include "elements/textelement.h"
#include "elements/scribbleelement.h"
#include "elements/audioelement.h"
#include "elements/photoelement.h"

#undef TOUCHE_SHOULD_SKIP_THIS

#include <QGraphicsView>
#include <QStateMachine>
#include <QPropertyAnimation>
#include <QLinearGradient>
#include "colaborative/manager.h"
#include "colaborative/dialog.h"
#include "colaborativecontroller.h"

Stage *Scene::m_items = Stage::makeInstance();

Scene::Scene(qreal x, qreal y, qreal width, qreal height, QObject *parent) :
        QGraphicsScene(x, y, width, height, parent),
        timerId(0),
        widget(NULL),
        modified(false)
{
    QGraphicsScene::setBackgroundBrush(QBrush(QPixmap(":/gfx/png/background.png")));

    QGraphicsScene::addItem(m_items);
    SliderItem *slider = new SliderItem(":/gfx/svg/zoom_slider.svg", ":/gfx/svg/zoom_icon.svg");
    slider->setMinimum(25);
    slider->setMaximum(200);
    slider->setValue(100);
    QGraphicsScene::addItem(slider);
    connect(slider, SIGNAL(valueChanged(uint)), this, SLOT(zoomChanged(uint)));

    bottomBar.push_back(new PushButtonItem(":/gfx/svg/factory-text.svg"));
    bottomBar.push_back(new PushButtonItem(":/gfx/svg/factory-scribble.svg"));
    bottomBar.push_back(new PushButtonItem(":/gfx/svg/icon_photo.svg"));
    bottomBar.push_back(new PushButtonItem(":/gfx/svg/icon_audio.svg"));
    bottomBar.push_back(new PushButtonItem(":/gfx/svg/import_item.svg"));

    //bar background
    QGraphicsItem *icon_bg = new QGraphicsSvgItem(":/gfx/svg/icons_bg.svg");
    QGraphicsScene::addItem(icon_bg);
    icon_bg->setPos(710., 15.);

    //    bottomBar.push_back(new PushButtonItem(":/gfx/svg/open-file.svg"));
    bottomBar[0]->setPos(290., 360.);
    bottomBar[1]->setPos(370., 360.);
    bottomBar[2]->setPos(723., 20.);
    bottomBar[3]->setPos(723., 75.);
    bottomBar[4]->setPos(450., 360.);

    QGraphicsScene::addItem(bottomBar[0]);
    QGraphicsScene::addItem(bottomBar[1]);
    QGraphicsScene::addItem(bottomBar[2]);
    QGraphicsScene::addItem(bottomBar[3]);
    QGraphicsScene::addItem(bottomBar[4]);

    connect(bottomBar[0], SIGNAL(clicked()), this, SLOT(addTextItem()));
    connect(bottomBar[1], SIGNAL(clicked()), this, SLOT(addScribbleItem()));
    connect(bottomBar[2], SIGNAL(clicked()), this, SLOT(add_photo_item()));
    connect(bottomBar[3], SIGNAL(clicked()), this, SLOT(addAudioItem()));
    connect(bottomBar[4], SIGNAL(clicked()), this, SLOT(addFromFile()));

    ColaborativeController::getInstance(m_items, this);
}

void Scene::itemMoved()
{
    if (!timerId) {
        timerId = startTimer(1000 / 25);
        time.start();
    }
}

void Scene::timerEvent(QTimerEvent *)
{
    QList<QGraphicsItem *> itemsList = items();
    bool itemsMoved = false;

    foreach (QGraphicsItem *item, itemsList) {
        if (dynamic_cast<DraggableToggleButton *>(item)) {
            StageActor *actor = reinterpret_cast<StageActor *>(item->data(0).value<QObject *>());
            if(actor){
                actor->calculateForces();

                if (actor->advance())
                    itemsMoved = true;
            }
        }
    }

    if (time.elapsed() > 2000 || !itemsMoved) {
        killPhysicsTimer();
    }

    m_items->update();
}

void Scene::zoomChanged(uint value)
{
//    0.25 <= factor <= 2.0
    qreal factor = static_cast<qreal>(value) / 100.;
    m_items->setScale(factor);
}

inline void Scene::addElement(Element *element)
{
    modified = true;
    m_items->addToGroup(element);
}

void Scene::addTextItem()
{
    this->addElement(new TextElement);
}

void Scene::addScribbleItem()
{
    this->addElement(new ScribbleElement);
}

void Scene::addAudioItem()
{
    this->addElement(new AudioElement);
}

void Scene::add_photo_item()
{
    widget = PhotoWidget::getInstance(m_items, views().first());
    widget->turnOn();
    widget->exec();
}

void Scene::killPhysicsTimer()
{
    killTimer(timerId);
    timerId = 0;
}

void Scene::newStage()
{
    //TODO: centralizar palco
    foreach(StageActor *actor, StageActor::actors()) {
        actor->deleteLater();
    }

    modified = false;
}

bool Scene::saveStage(const QString &file)
{
    bool saved = m_items->save(file);

    if(saved) {
        modified = false;
        return true;
    } else {
        return false;
    }
}

void Scene::loadStage(const QString &file)
{
    m_items->load(file);
    modified = false;
}

void Scene::addFromFile()
{
    QFileInfo file = QFileDialog::getOpenFileName(views().first(), "Choose a file to import", QDir::homePath(), QString::fromUtf8("Scribble (*.png);;Photo (*.jpg);;Audio (*.spx)"));

    if(file.exists()){
        Element *element = NULL;

        if(file.suffix() == "png"){
            element = new ScribbleElement;
        }else if((file.suffix() == "jpg")){
            element = new PhotoElement;
        }else if(file.suffix() == "spx"){
            element = new AudioElement;
        }

        if(element){
            static QString nullXml;
            QString newFile = element->type() + '_' + element->id() + '.' + file.suffix();
            QFile::copy(file.filePath(), newFile);
            element->load(nullXml, newFile);
            m_items->addToGroup(element);
        }
    }
}
